tool
extends VBoxContainer



var nodes:Dictionary # 节点数据
var title:String setget set_title # 选项卡名称
var fPath:String # 节点数据文件的路径
var is_lazy_load = false # 是否懒加载

var is_toolbarview = false setget set_is_toolbarview#是否是toolbar视图

var is_en = false setget set_is_en # 默认显示中文

func set_is_toolbarview(value:bool):
	is_toolbarview = value
	# 清空
	var VBox = $"scroll/VBoxContainer"# VBox容器 - 用于承载分组和分组下的按钮
	var gups = VBox.get_children() # 所有子节点
	for node in gups:
		VBox.remove_child(node)
	var optsBtn:OptionButton = $"ctl/OptionButton" # 分组下拉列表
	optsBtn.clear()
	# 重新加载
	load_page()

func _enter_tree():
	if is_lazy_load == false: # 非懒加载模式
		load_page()
	pass

func set_title(value):
	var tabControl  = $"."
	tabControl.name = value # 修改选项卡名称

func set_is_en(value:bool):
	is_en = value
	# 清空
	var VBox = $"scroll/VBoxContainer"# VBox容器 - 用于承载分组和分组下的按钮
	var gups = VBox.get_children() # 所有子节点
	for node in gups:
		VBox.remove_child(node)
	var optsBtn:OptionButton = $"ctl/OptionButton" # 分组下拉列表
	optsBtn.clear()
	# 重新加载
	load_page()
	pass

# 按fPath指定的数据文件加载相应页面的内容
func load_page():
	var tabControl  = $"."
	var optsBtn = $"ctl/OptionButton" # 分组下拉列表
	var VBox = $"scroll/VBoxContainer"# VBox容器 - 用于承载分组和分组下的按钮
	if VBox.get_child_count() == 0:
		if not optsBtn.items.has("全部分组"):
			optsBtn.add_item("全部分组")
		for gup in nodes:
			# 添加分组名称到显示模式下拉框
			optsBtn.add_item(nodes[gup].gup_name)
			# 创建分组按钮
			var gupBtn = Button.new() 
			gupBtn.text = nodes[gup].gup_name # 分组名称
			gupBtn.flat = true # 平面化按钮
			gupBtn.size_flags_horizontal = SIZE_EXPAND_FILL
			gupBtn.connect("pressed",self,"gup_btn_click",[gupBtn.text])
			VBox.add_child(gupBtn)
			# 创建GridContainer
			var gupContainer = GridContainer.new()
			
			# 实现响应式布局
			var width
			if is_toolbarview:
				width = 55
			else:
				width = 300
			var clm = floor(rect_size.x / width)
			if clm < 1 :clm  =  1 
			gupContainer.columns = clm
			
			
			gupContainer.set("custom_constants/vseparation",10) # 水平间隔
			gupContainer.set("custom_constants/hseparation",10) # 垂直间隔
			VBox.add_child(gupContainer)

			# 添加Control类型节点按钮
			for ctl in nodes[gup].items:
				var hbox:HBoxContainer = HBoxContainer.new() # 水平盒子 - 装控件按钮和帮助文档按钮
				hbox.size_flags_horizontal  = SIZE_EXPAND_FILL # size_flags
				gupContainer.add_child(hbox)

				# 控件按钮
				var ctlBtn:Button = Button.new()
				ctlBtn.clip_text = true # 隐藏多出的文本
				ctlBtn.name = "ctlbtn_" + ctl[0] # "ctlbtn_"前缀加上类名
				if is_en: # 如果切换显示英文
					ctlBtn.text = ctl[0] # 英文名称
				else:
					ctlBtn.text = ctl[1] # 中文名称
				if is_toolbarview:# 如果是ToolBar视图
					ctlBtn.text = "" # 图标不显示
				ctlBtn.hint_tooltip = ctl[0] + " " + ctl[1] + "\n\n" + ctl[2] # 鼠标提示文本
				ctlBtn.icon = get_icon(ctl[0],"EditorIcons") # 显示图标
				ctlBtn.size_flags_horizontal  = SIZE_EXPAND_FILL # size_flags
				ctlBtn.connect("gui_input",self,"ctl_btn_click",[ctl[0]]) # 将所有按钮的pressed信号连接到同一个函数
				hbox.add_child(ctlBtn)
				if not is_toolbarview:# 如果不是ToolBar视图
					# 帮助按钮
					var hlpBtn:Button = Button.new() 
					hlpBtn.name = "hlpbtn_" + ctl[0] # "hlpbtn_"前缀加上类名
					hlpBtn.text = "" # 文本为空
					hlpBtn.hint_tooltip = "查看内置文档" # 鼠标提示文本
					hlpBtn.icon = get_icon("Help","EditorIcons") # 显示图标
					hlpBtn.connect("pressed",self,"hlp_btn_click",[ctl[0]])
					hbox.add_child(hlpBtn)

				
# 处理按钮信号
func ctl_btn_click(event:InputEvent,nodeType:String):
	if sel(): # 非空场景 - 有选中节点
		if event is InputEventMouseButton and event.pressed:
			if event.button_index == BUTTON_LEFT: # 左键单击
				if event.control: # Ctrl+左键点击
					var plug = EditorPlugin.new()
					plug.get_editor_interface().get_script_editor()._help_class_goto(nodeType)
				else:
					# 添加子节点
					var node:Node = ClassDB.instance(nodeType) # 按照类型名称添加节点
					sel().add_child(node)
					node.owner = get_tree().edited_scene_root # 设置owner为场景根节点	
			elif event.button_index == BUTTON_RIGHT:# 右键单击
				# 修改节点类型
				replace_node(nodeType)
	else: # 空场景 - 没有选中节点
		if event is InputEventMouseButton and event.pressed:
			if event.button_index == BUTTON_LEFT: # 左键单击
				empty_scene_add_root(nodeType)


# 替换节点类型
func replace_node(nodeType:String):
	var plug = EditorPlugin.new()
	var root = plug.get_editor_interface().get_tree().root
	
	var scene_tree_dock = root.find_node("Scene",true,false)
	scene_tree_dock._tool_selected(8)
	var create_dialog = find_child_as_class(scene_tree_dock,"CreateDialog")
	# 搜索框
	var hs = create_dialog.get_child(3)
	var vb = hs.get_child(1)
	var mg = vb.get_child(1)
	var txt:LineEdit = mg.get_child(0).get_child(0)
	# "创建"按钮
	var hb = create_dialog.get_child(2)
	var creBtn:Button = hb.get_child(1)
	txt.text = nodeType # 修改搜索关键字
	txt.emit_signal("text_changed",nodeType) # 触发“文本改变”信号
	creBtn.emit_signal("pressed") # 触发“创建”按钮pressed信号

# 空场景添加根节点
func empty_scene_add_root(nodeType:String):
	var plug = EditorPlugin.new()
	var root = plug.get_editor_interface().get_tree().root
	
	if not plug.get_editor_interface().get_edited_scene_root():# 当前场景为空场景
		# 新建根节点
		var scene_tree_dock = root.find_node("Scene",true,false)
		scene_tree_dock._tool_selected(0)
		var create_dialog = find_child_as_class(scene_tree_dock,"CreateDialog")
		# 搜索框
		var hs = create_dialog.get_child(3)
		var vb = hs.get_child(1)
		var mg = vb.get_child(1)
		var txt:LineEdit = mg.get_child(0).get_child(0)
		# "创建"按钮
		var hb = create_dialog.get_child(2)
		var creBtn:Button = hb.get_child(1)
		txt.text = nodeType # 修改搜索关键字
		txt.emit_signal("text_changed",nodeType) # 触发“文本改变”信号
		creBtn.emit_signal("pressed") # 触发“创建”按钮pressed信号

# 返回对应类名的子节点
func find_child_as_class(node:Node,className:String):
	var children = node.get_children()
	for child in children:
		if child.is_class(className):
			return child

# 处理帮助按钮信号 - 2021年8月27日 来自timothyqiu兄的提点
func hlp_btn_click(nodeType:String):
	var plug = EditorPlugin.new()
	plug.get_editor_interface().get_script_editor()._help_class_goto(nodeType)

# 处理分组按钮信号 - 点击分组按钮，隐藏其分组
func gup_btn_click(gupName:String):
	var VBox = $"scroll/VBoxContainer"# VBox容器 - 用于承载分组和分组下的按钮
	var gups = VBox.get_children() # 所有子节点
	for node in gups:
		if node is Button and node.text == gupName:
			gups[node.get_index()+1].visible = not gups[node.get_index()+1].visible


# 判断并返回当前场景中选中的节点
func sel():
	var plug = EditorPlugin.new()
	var sels = plug.get_editor_interface().get_selection().get_selected_nodes() # 获取当前选中的节点集合
	var _sel
	if sels.size() == 1:
		_sel =sels[0]
	else:
		_sel = null
	return _sel

# 显示模式下拉列表改变选项
func _on_OptionButton_item_selected(index):
	var optsBtn = $"ctl/OptionButton"
	var VBox = $"scroll/VBoxContainer"# VBox容器 - 用于承载分组和分组下的按钮
	var gups = VBox.get_children() # 所有子节点
	var gupBtns = [] # 分组按钮集合
	for node in gups:
		if node is Button:
			gupBtns.append(node)
	if index == 0: # 显示全部分组
		for gupBtn in gupBtns:
			gupBtn.visible = true # 显示分组按钮
			gups[gupBtn.get_index()+1].visible = true # 显示分组
	else: # 显示单个分组
		for gupBtn in gupBtns:
			if gupBtn.text != optsBtn.text:
				gupBtn.visible = false # 隐藏分组按钮
				gups[gupBtn.get_index()+1].visible = false # 隐藏分组
			else:
				gupBtn.visible = true # 显示分组按钮
				gups[gupBtn.get_index()+1].visible = true # 显示分组
	pass # Replace with function body.



# 改变主题时，更改按钮图标 - 2021年8月27日 来自timothyqiu兄的提点
func _notification(what):
	match what:
		NOTIFICATION_THEME_CHANGED:
			for node in get_children():
				if not node is GridContainer:
					continue
				for button in node.get_children():
					if button is Button:
						button.icon = get_icon(button.name.replace("ctlbtn_",""),"EditorIcons")



func _on_VBoxContainer_resized():
	var width
	if is_toolbarview:
		width = 55
	else:
		width = 300
	# 实现响应式布局
	var VBox = $"scroll/VBoxContainer"# VBox容器 - 用于承载分组和分组下的按钮
	var gups = VBox.get_children() # 所有子节点
	var clm = floor(rect_size.x / width)
	if clm < 1 :clm  =  1 
	for node in gups:
		if node is GridContainer:
			node.columns = clm
	pass 

